/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007 Intel Corporation. All Rights Reserved.
//
//
*/

#include "umc_defs.h"
#if defined(UMC_ENABLE_AVS_VIDEO_DECODER) || \
    defined(UMC_ENABLE_AVS_VIDEO_ENCODER)

#include "umc_avs_coeffs_buffer.h"
#include "ipps.h"

namespace UMC
{

AVSCoeffsBuffer::AVSCoeffsBuffer(void)
{
    m_pBuffer = NULL;
    m_iBufferSize = 0;

    m_pFree = NULL;
    m_iFreeSize = 0;

    m_pUsed = NULL;
    m_iUsedSize = 0;

    m_iDummy = 0;

    m_iMinPieceToWrite = 0;

} // AVSCoeffsBuffer::AVSCoeffsBuffer(void)

AVSCoeffsBuffer::~AVSCoeffsBuffer(void)
{
    Close();

} // AVSCoeffsBuffer::~AVSCoeffsBuffer(void)

Status AVSCoeffsBuffer::Close(void)
{
    if (m_pBuffer)
        ippsFree(m_pBuffer);

    m_pBuffer = NULL;
    m_iBufferSize = 0;

    m_pFree = NULL;
    m_iFreeSize = 0;

    m_pUsed = NULL;
    m_iUsedSize = 0;

    m_iDummy = 0;

    m_iMinPieceToWrite = 0;

    return UMC_OK;

} // Status AVSCoeffsBuffer::Close(void)

Status AVSCoeffsBuffer::Init(size_t iMinPieceToWrite, Ipp32s iNumPieces)
{
    size_t iBufferSize;

    iBufferSize = iMinPieceToWrite * iNumPieces;

    // check the buffer's parameters
    if ((m_iMinPieceToWrite == iMinPieceToWrite) &&
        (m_iBufferSize == iBufferSize))
        return UMC_OK;

    // release the object before initialization
    Close();

    // allocate the buffer
    m_pBuffer = ippsMalloc_16s((int) iBufferSize);
    if (NULL == m_pBuffer)
        return UMC_ERR_ALLOC;

    // set the pointers
    m_iBufferSize = iBufferSize;
    m_pFree = m_pBuffer;
    m_iFreeSize = iBufferSize;
    m_pUsed = m_pBuffer;
    m_iUsedSize = 0;
    m_iMinPieceToWrite = iMinPieceToWrite;

    return UMC_OK;

} // Status AVSCoeffsBuffer::Init(Ipp32s iMinPieceToWrite, Ipp32s iNumPieces)

Ipp16s *AVSCoeffsBuffer::GetFree(void)
{
    // check the size of free space
    if (m_iFreeSize < m_iMinPieceToWrite)
        return NULL;

    return m_pFree;

} // Ipp16s *AVSCoeffsBuffer::GetFree(void)

Ipp16s *AVSCoeffsBuffer::GetUsed(void)
{
    // check the size of used space
    if (0 == m_iUsedSize)
        return NULL;

    return m_pUsed;

} // Ipp16s *AVSCoeffsBuffer::GetUsed(void)

void AVSCoeffsBuffer::AdvanceFree(size_t iAdvance)
{
    // advance pointer & decrease available space
    m_pFree += iAdvance;
    m_iFreeSize -= iAdvance;
    m_iUsedSize += iAdvance;

    // buffer at the end is to small
    if (m_pBuffer + m_iBufferSize - m_iMinPieceToWrite < m_pFree)
    {
        size_t iLeft = m_pBuffer + m_iBufferSize - m_pFree;

        m_pFree = m_pBuffer;
        m_iFreeSize -= iLeft;
        m_iDummy = iLeft;
    }

} // void AVSCoeffsBuffer::AdvanceFree(size_t iAdvance)

void AVSCoeffsBuffer::AdvanceUsed(size_t iAdvance)
{
    // advance pointer & decrease available space
    m_pUsed += iAdvance;
    m_iUsedSize -= iAdvance;
    m_iFreeSize += iAdvance;

    // check the buffer's end state
    if (m_pBuffer + m_iBufferSize == m_pUsed + m_iDummy)
    {
        m_pUsed = m_pBuffer;
        m_iFreeSize += m_iDummy;
        m_iDummy = 0;
    }

} // void AVSCoeffsBuffer::AdvanceUsed(size_t iAdvance)

size_t AVSCoeffsBuffer::GetBufferSize(void)
{
    return m_iBufferSize;

} // size_t AVSCoeffsBuffer::GetBufferSize(void)

} // namespace UMC

#endif // defined(UMC_ENABLE_AVS_VIDEO_DECODER) ||
